﻿using System;
using System.Windows;
using CThru.Silverlight;
using Core.Infrastructure.Menu;
using Core.Infrastructure.ScreenManager;
using NUnit.Framework;
using TypeMock.ArrangeActAssert;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Unity;

namespace Core.Test
{
    [TestFixture]
    public class ConfigTest
    {
        public Config config = null;
        public IUnityContainer mockContainer = null;

        [SetUp, SilverlightSetUp]
        public void SetUpTest()
        {
            config = new Config();
            mockContainer = Isolate.Fake.Instance<IUnityContainer>();
        }

        [TearDown]
        public void TearDownTest()
        {
            config = null;
            mockContainer = null;
        }

        [Test, SilverlightUnitTest]
        public void CreateModuleCatalog_NotEmptyString_PRISMMethodCalledCorrectly()
        {
            Isolate.Fake.StaticMethods<ModuleCatalog>();
            Uri uri = new Uri("agebe", UriKind.Relative);
            Isolate.WhenCalled(() => ModuleCatalog.CreateFromXaml(uri)).DoInstead(context => new ModuleCatalog());

            IModuleCatalog retValue = config.CreateModuleCatalog("agebe");

            Assert.NotNull(retValue);
        }

        [Test, SilverlightUnitTest]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateModuleCatalog_NullString_ThrowArgumentNullException()
        {
            IModuleCatalog retValue = config.CreateModuleCatalog("");
        }

        [Test, SilverlightUnitTest]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateModuleCatalog_EmptyString_ThrowArgumentNullException()
        {
            IModuleCatalog retValue = config.CreateModuleCatalog((string)null);
        }

        [Test, SilverlightUnitTest]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Initialize_NullReference_ExceptionThrown()
        {
            config.Initialize(null);
        }

        [Test, SilverlightUnitTest]
        public void Initialize_ValidContainer_ObjectsRegistered()
        {
            IShellViewModel svm = Isolate.Fake.Instance<IShellViewModel>();
            ShellView sv = Isolate.Fake.Instance<ShellView>();

            config.ShellView = sv;
            Isolate.WhenCalled(() => mockContainer.Resolve<IShellViewModel>()).DoInstead(c => svm);
            
            config.Initialize(mockContainer);
            Isolate.Verify.WasCalledWithExactArguments(
                () => mockContainer.RegisterType<IShellViewModel, ShellViewModel>());
            Isolate.Verify.WasCalledWithExactArguments(
                () => mockContainer.RegisterType<IMenu, Menu>());
        }

        [Test, SilverlightUnitTest]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateAndSetRootVisual_NullReference_RootVisualNotSet()
        {
            config.CreateAndSetRootVisual(null);
        }

        [Test, SilverlightUnitTest]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RegisterScreenManeger_NullReference_ExceptionThrown()
        {
            config.RegisterScreenManeger(null);
            Isolate.WhenCalled(() => config.RegisterScreenManeger(null))
                .WillThrow(new ArgumentNullException("Unity container must be specified"));
        }

        [Test, SilverlightUnitTest]
        public void RegisterScreenManeger_ValidContainerReference_ScreenManagerObjectsRegistered()
        {
            config.RegisterScreenManeger(mockContainer);

            var cclf = Isolate.Fake.Instance<ContainerControlledLifetimeManager>();

            Isolate.Verify.WasCalledWithAnyArguments(
                () => mockContainer.RegisterType<IScreenFactoryRegistry, ScreenFactoryRegistry>(cclf));

            Isolate.Verify.WasCalledWithAnyArguments(
                () => mockContainer.RegisterType<ScreenManager, ScreenManager>(cclf));
        }
    }
}
